#pragma once

#include <iostream>
#include <string>
#include <vector>
#include <cstring>

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#include <unistd.h>
#include <poll.h>

static const uint16_t defaultport = 8082;
static const int backlog = 10;
static const int fd_max_num = 64;

static const int defaultfd = -1;
static const int non_event = 0;

class PollServer
{
public:
    PollServer(const uint16_t port = defaultport)
        : _listen_sockfd(0), _port(port)
    {
        for(int i = 0; i < fd_max_num; i++)
        {
            _eventfds[i].fd = defaultfd;
            _eventfds[i].events = non_event;
            _eventfds[i].revents = non_event;
        }
    }
    // 初始化服务器
    void Init()
    {
        // 创建监听套接字
        _listen_sockfd = socket(AF_INET, SOCK_STREAM, 0);
        if (_listen_sockfd < 0)
        {
            std::cerr << "listensockfd socket fail" << std::endl;
            exit(-1);
        }
        std::cout << "[listensockfd socket success]" << std::endl;

        int opt = 1;
        setsockopt(_listen_sockfd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt));

        // 绑定端口号
        struct sockaddr_in server;
        memset(&server, 0, sizeof(server));
        server.sin_family = AF_INET;
        server.sin_port = htons(_port);
        server.sin_addr.s_addr = INADDR_ANY;

        int retbind = bind(_listen_sockfd, (const struct sockaddr *)&server, sizeof(server));
        if (retbind < 0)
        {
            std::cerr << "listensockfd bind fail" << std::endl;
            exit(-1);
        }
        std::cout << "[listensockfd bind success]" << std::endl;

        // 开始监听
        int retlisten = listen(_listen_sockfd, backlog);
        if (retlisten < 0)
        {
            std::cerr << "listensockfd bind fail" << std::endl;
            exit(-1);
        }
        std::cout << "[listensockfd listen......]" << std::endl;
    }

    // 启动服务器
    void Start()
    {
        _eventfds[0].fd = _listen_sockfd;
        _eventfds[0].events = POLLIN;
        int timeout = 3000;
        while (true)
        {

            int ret = poll(_eventfds, fd_max_num, timeout);
            if (ret < 0)
            {
                std::cerr << "poll fail" << std::endl;
            }
            else if (ret == 0)
            {
                std::cout << "poll time out" << std::endl;
            }
            else
            {
                std::cout << "get a new link" << std::endl;
                // 处理事件
                HandlerEvent();
            }
        }
    }

    void HandlerEvent()
    {
        for (int i = 0; i < fd_max_num; i++)
        {
            int fd = _eventfds[i].fd;
            if (fd == defaultfd)
                continue;

            // fd的读事件是否就绪
            if (_eventfds[i].revents & POLLIN)
            {
                // 是监听套接字
                if (fd == _listen_sockfd)
                {
                    // 处理监听事件
                    struct sockaddr_in client;
                    memset(&client, 0, sizeof(client));
                    socklen_t len = sizeof(client);

                    //获取新连接
                    int sockfd = accept(_listen_sockfd, (struct sockaddr *)&client, &len);
                    if (sockfd < 0)
                    {
                        std::cerr << "accept fail" << std::endl;
                        continue;
                    }
                    //将sockfd放入到读事件数组中
                    int pos = 1;
                    for (; pos < fd_max_num; pos++)
                    {
                        if (_eventfds[pos].fd == defaultfd)
                            break;
                    }
                    //数组如果满了就关闭连接
                    if (pos == fd_max_num)
                    {
                        //可以把_eventfds设置成指针，满了扩容即可
                        std::cerr << "warning _read_array isfull" << std::endl;
                        close(sockfd);
                    }
                    else
                    {
                        _eventfds[pos].fd = sockfd;
                        _eventfds[pos].events = POLLIN;
                    }
                }
                else
                {
                    // 处理读事件
                    char buffer[1024];
                    //这里的读数据没有处理粘包问题和是否为一个完整报文的问题，需要应用层协议定制
                    ssize_t n = read(fd, buffer, sizeof(buffer) - 1);  
                    if (n < 0)
                    {
                        std::cerr << "read fail" << std::endl;
                        close(fd);
                        _eventfds[i].fd = defaultfd;
                        _eventfds[i].events = 0;
                    }
                    else if (n == 0)
                    {
                        std::cerr << "client quit" << std::endl;
                        close(fd);
                        _eventfds[i].fd = defaultfd;
                        _eventfds[i].events = 0;
                    }
                    else
                    {
                        buffer[n] = '\0';
                        std::cout << "client say#" << buffer << std::endl;
                    }
                }
            }
        }
    }

private:
    int _listen_sockfd;
    uint16_t _port;
    struct pollfd _eventfds[fd_max_num];
};